import { SearchOutlined, CloseCircleFilled, MenuOutlined } from '@ant-design/icons'
import { Input, Checkbox } from 'antd'
import { OrderedMap } from 'immutable'
import GroupItem from '@/desktop/components/GroupItem'
import { type BaseGroup } from '@/services/contact-types'
import GroupList from './List'
import { useDrag, type DroppedInfo } from './drag'
import type { QywxMap, GroupMap, GroupFilter, ConfirmChoosable } from './hooks'
import { useGroups, useChoosed, useQywxMap } from './hooks'
import './index.less'

export type { QywxMap, GroupMap, GroupFilter, ConfirmChoosable } from './hooks'

const classPrefix = 'qun-choose-groups'
const cls = (name: string) => `${classPrefix}-${name}`

export default function ChooseGroups(props: {
  // 数据处理
  combine?: boolean // 为 ture 则把多个企业微信的同一个群合并起来，详见 useGroups()
  sortable?: boolean // 是否开启“已选中的群”的排序
  qywxs?: QywxMap
  groups?: GroupMap | GroupFilter
  filter?: GroupFilter

  // 选中状态处理
  choosed: string[]
  setChoosed: (choosed: string[]) => void
  choosable?: ConfirmChoosable

  // 界面扩展
  filterView?: JSX.Element // 与 filter 搭配使用，提供界面来修改 filter 参数
  choosedPrefix?: JSX.Element
  choosedSuffix?: JSX.Element
}) {
  const {
    qywxs: inputQywxMap,
    groups: inputGroupMap,
    filter,
    combine = false,
    sortable = false,
    choosed,
    setChoosed,
    choosable,
    filterView,
    choosedPrefix,
    choosedSuffix,
  } = props

  const qywxMap = useQywxMap(
    combine
      ? OrderedMap() // combine 模式不需要企业微信数据
      : inputQywxMap,
  )

  const { allGroupMap, search, setSearch, filteredGroups } = useGroups(
    inputGroupMap,
    filter,
    combine,
  )

  const { choosableFilteredIds, filteredChoosedAll, switchChoose, switchChooseAll } = useChoosed({
    allGroupMap,
    filteredGroups,
    confirmChoosable: choosable,
    choosed,
    setChoosed,
  })

  const onDropped = useCallback(
    ({ draggingId, prevId }: DroppedInfo) => {
      const updated = choosed.filter(v => v !== draggingId)
      if (prevId !== null) {
        const prevIndex = updated.indexOf(prevId)
        updated.splice(prevIndex + 1, 0, draggingId)
      } else {
        updated.unshift(draggingId)
      }
      setChoosed(updated)
    },
    [choosed, setChoosed],
  )
  const { props: dragProps } = useDrag(onDropped)

  const isChoosable = useCallback(
    (group: BaseGroup) => choosableFilteredIds.has(group.id),
    [choosableFilteredIds],
  )
  const listData = useMemo(
    () => ({ groups: filteredGroups, qywxMap, isChoosable, choosed, switchChoose }),
    [filteredGroups, qywxMap, isChoosable, choosed, switchChoose],
  )

  return <div className="qun-choose-groups">
    <div className={cls('groups-col')}>
      <div className={cls('filter-wrap')}>
        <div className={cls('search')}>
          <Input
            suffix={<SearchOutlined />}
            placeholder="查找群"
            value={search}
            onChange={e => setSearch(e.target.value)}
          />
        </div>

        {filterView ? filterView : null}
      </div>

      <div className={cls('choose-all')}>
        <Checkbox
          disabled={!choosableFilteredIds.size}
          checked={filteredChoosedAll !== 0}
          indeterminate={filteredChoosedAll === 2}
          onClick={switchChooseAll}
        >
          全选{choosableFilteredIds.size ? `（${choosableFilteredIds.size}）` : ''}
        </Checkbox>
      </div>

      <div className={cls('choose-list-wrap')}>
        <GroupList data={listData} />
      </div>
    </div>

    <div className={cls('choosed-col')}>
      {choosedPrefix ?? null}

      <section className={cls('choosed-panel')}>
        <h2>已选中 {choosed.length} 个群</h2>
        <div className={cls('choosed-list')}>
          {choosed.map(id => <ChoosedGroupItem
            key={id}
            id={id}
            allGroupMap={allGroupMap}
            qywxMap={qywxMap}
            switchChoose={switchChoose}
            dragProps={sortable ? dragProps : undefined}
          />)}
        </div>
      </section>

      {choosedSuffix ?? null}
    </div>
  </div>
}

function ChoosedGroupItem(props: {
  id: string
  allGroupMap: GroupMap
  qywxMap: QywxMap
  switchChoose: (id: string) => void
  dragProps?: React.HTMLAttributes<HTMLElement>
}) {
  const { id, allGroupMap, qywxMap, switchChoose, dragProps } = props

  const group = allGroupMap.get(id)
  if (!group) return null

  return <div key={id} data-group-id={id} className={cls('choosed-item')}>
    {dragProps ? <MenuOutlined className={cls('choosed-item-move')} {...dragProps} /> : null}
    <GroupItem contact={group} qywx={qywxMap.get(group.ownerWxid)} />
    <CloseCircleFilled className={cls('choosed-item-remove')} onClick={() => switchChoose(id)} />
  </div>
}
